package Tree;

import java.util.*;

/**
 * @Classname JZ34二叉树中和为某一值的路径
 * @Description TODO
 * @Date 2023/2/23 9:53
 * @Created by xjl
 */
public class JZ34二叉树中和为某一值的路径 {

    public class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

        TreeNode(int val) {
            this.val = val;
        }

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    /**
     * @description 二叉树中和为某一路径的
     * @param: root
     * @param: target
     * @date: 2023/2/23 9:54
     * @return: java.util.List<java.util.List < java.lang.Integer>>
     * @author: xjl
     */
    // 存放的结果
    List<List<Integer>> ret = new LinkedList<List<Integer>>();
    // 存放的是路径
    Deque<Integer> path = new LinkedList<Integer>();

    public List<List<Integer>> pathSum(TreeNode root, int target) {
        dfs(root, target);
        return ret;
    }

    // 遍历二叉树
    private void dfs(TreeNode root, int target) {
        if (root == null) {
            return;
        }
        path.offerLast(root.val);
        target -= root.val;
        if (root.left == null && root.right == null && target == 0) {
            ret.add(new LinkedList<Integer>(path));
        }
        // 先添加左子树
        dfs(root.left, target);
        // 先添加右子树
        dfs(root.right, target);
        // 回溯算法进行
        path.pollLast();
    }

    Map<TreeNode, TreeNode> map = new HashMap<>();

    /**
     * @description 采用的广度遍历的方式来实现
      * @param: root
     * @param: target
     * @date: 2023/2/23 15:23
     * @return: java.util.List<java.util.List<java.lang.Integer>>
     * @author: xjl
    */
    public List<List<Integer>> pathSum2(TreeNode root, int target) {
        if (root == null) {
            return ret;
        }

        Queue<TreeNode> queueNode = new LinkedList<TreeNode>();
        Queue<Integer> queueSum = new LinkedList<Integer>();
        queueNode.offer(root);
        queueSum.offer(0);

        while (!queueNode.isEmpty()) {
            TreeNode node = queueNode.poll();
            int rec = queueSum.poll() + node.val;
            if (node.left == null && node.right == null && rec == target) {
                getPath(node);
            } else {
                if (node.left != null) {
                    // 存储当前节点的父节点
                    map.put(node.left, node);
                    // 加入队列
                    queueNode.offer(node.left);
                    // 加入当前的值和存储在队列中
                    queueSum.offer(rec);
                }
                if (node.right != null) {
                    // 存储当前节点的父节点
                    map.put(node.right, node);
                    queueNode.offer(node.right);
                    queueSum.offer(rec);
                }
            }
        }
        return ret;
    }

    public void getPath(TreeNode node) {
        List<Integer> temp = new LinkedList<Integer>();
        //拿到当前节点加入其中，然后在只想父节点位置。
        while (node != null) {
            temp.add(node.val);
            node = map.get(node);
        }
        //然后将结果翻转回来就是当前合适的路径
        Collections.reverse(temp);
        // 将符合的结果加入到其中。
        ret.add(new LinkedList<Integer>(temp));
    }
}
